package com.ruoyi.system.service.impl;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.ruoyi.common.enums.UserCourseTimeStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.AliyunSmsUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.SpokenUserCourseTimeMapper;
import com.ruoyi.system.service.*;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class SpokenUserCourseTimeServiceImpl implements ISpokenUserCourseTimeService {

    @Autowired
    SpokenUserCourseTimeMapper userCourseTimeMapper;

    @Autowired
    ISpokenTeacherCourseTimeService teacherCourseTimeService;

    @Autowired
    ISpokenTeacherService teacherService;

    @Autowired
    ISpokenUserService userService;

    @Autowired
    ISpokenOrderService orderService;

    @Autowired
    ISpokenCourseTimeService courseTimeService;

    @Autowired
    AliyunSmsUtils aliyunSmsUtils;


    @Override
    public int insert(List<SpokenUserCourseTime> list) {
        return userCourseTimeMapper.insert(list);
    }

    @Override
    public int update(SpokenUserCourseTime userCourseTime) {
        return userCourseTimeMapper.update(userCourseTime);
    }

    /**
     * 根据主键ID查询
     */
    @Override
    public SpokenUserCourseTime selectIdByPrimaryKey(Long uctId){
        return userCourseTimeMapper.selectIdByPrimaryKey(uctId);
    }

    @Override
    public List<SpokenUserCourseTime> select(SpokenUserCourseTime userCourseTime) {
        return userCourseTimeMapper.select(userCourseTime);
    }

    @Override
    public Integer selectCountByOrderId(Long orderId) {
        return userCourseTimeMapper.selectCountByOrderId(orderId);
    }

    @Override
    public Integer mobileSelectCountByOrderId(Long orderId) {
        return userCourseTimeMapper.mobileSelectCountByOrderId(orderId);
    }


    @Override
    public List<SpokenUserCourseTime> selectUserCourseTimeByOrderId(Long orderId) {
        return userCourseTimeMapper.selectUserCourseTimeByOrderId(orderId);
    }

    @Override
    public List<SpokenUserCourseTime> selectUserCourseTimeByUserId(Long userId) {
        return userCourseTimeMapper.selectUserCourseTimeByUserId(userId);
    }

    @Override
    public List<SpokenUserCourseTime> selectTeacherIdByDate(String chooseDate, Long userId) {
        return userCourseTimeMapper.selectTeacherIdByDate(chooseDate, userId);
    }

    @Override
    public Integer selectLessonNumByTeacherId(Long userId, Long teacherId) {
        return userCourseTimeMapper.selectLessonNumByTeacherId(userId, teacherId);
    }

    @Override
    public Integer selectCancelLessonNumByTeacherId(Long userId, Long teacherId) {
        return userCourseTimeMapper.selectCancelLessonNumByTeacherId(userId, teacherId);
    }

    @Override
    public int cancelLessonNum(Long uctId) {
        SpokenUserCourseTime userCourseTime = selectIdByPrimaryKey(uctId);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        String strDate = userCourseTime.getChooseDate() + " " + userCourseTime.getCourseTime().getEndTime();
        LocalDateTime endTime = LocalDateTime.parse(strDate, formatter);
        if(LocalDateTime.now().isBefore(endTime)){
            throw new ServiceException("未到结束时间，无法消课");
        }
        // 修改为消课状态
        userCourseTime.setStatus(UserCourseTimeStatus.CANCEL_LESSON.getCode());
        userCourseTime.setCancelLessonTime(LocalDateTime.now());
        return userCourseTimeMapper.update(userCourseTime);
    }

    /**
     * 查询昨日、待消课的课时
     * @return
     */
    @Override
    public List<SpokenUserCourseTime> selectWaitCancelLesson() {
        List<SpokenUserCourseTime> spokenUserCourseTimes = userCourseTimeMapper.selectWaitCancelLesson();
        return spokenUserCourseTimes;
    }

    /**
     * 请假
     * @param uctId
     * @return
     */
    @Override
    public int leaveLesson(Long uctId) {
        SpokenUserCourseTime userCourseTime = selectIdByPrimaryKey(uctId);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        String strDate = userCourseTime.getChooseDate() + " " + userCourseTime.getCourseTime().getStartTime();
        LocalDateTime startTime = LocalDateTime.parse(strDate, formatter);
        if(LocalDateTime.now().isAfter(startTime)){
            throw new ServiceException("课时开始时间已过，无法请假");
        }
        long mill = System.currentTimeMillis();
        long startTimeMill = Timestamp.valueOf(startTime).getTime();
        // 距离上课时间小于两小时
        if(startTimeMill - mill < 2 * 60 * 60 * 1000 ){
            throw new ServiceException("距离开始时间不足2小时，无法请假");
        }
        // 当前课时修改为请假状态，其他人可选
        userCourseTime.setStatus(UserCourseTimeStatus.LEAVE.getCode());
        int rows = userCourseTimeMapper.update(userCourseTime);

        // 发送请假通知
        SpokenTeacher spokenTeacher = teacherService.selectById(userCourseTime.getTeacherId());
        String teacherPhone = spokenTeacher.getSysUser().getPhonenumber();
        SpokenUser spokenUser = userService.selectById(userCourseTime.getUserId());
        String studentNickName = spokenUser.getSysUser().getNickName();
        String englishName = !StringUtils.isEmpty(spokenUser.getEnglishName()) ? spokenUser.getEnglishName() : "暂无";
        DateTimeFormatter formatDate = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter formatTime = DateTimeFormatter.ofPattern("HH:mm:ss");
        String datetime = userCourseTime.getChooseDate().format(formatDate) + " " +  userCourseTime.getCourseTime().getStartTime().format(formatTime);
        SendSmsResponse sendSmsResponse = aliyunSmsUtils.sendMessage(aliyunSmsUtils.getSignNameOverseas(), aliyunSmsUtils.getLeaveTemplateCode(),
                teacherPhone,
                "{\"wechatid\": \"" + studentNickName + "\", \"name\": \"" + englishName + "\", \"date\": \"" + datetime + "\"}");
        // 发送成功
        if(sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
            System.out.println(studentNickName + "请假通知成功");
            System.out.println("{\"wechatid\": \"" + studentNickName + "\", \"name\": \"" + englishName + "\", \"date\": \"" + datetime + "\"}");
        }
        return rows;
    }

    /**
     * 根据教师ID、开始日期、结束日期查询时间段内的课时选择情况
     * @param teacherId
     * @return
     */
    @Override
    public List selectCourseTimeStatusByDate(Long teacherId, String startDateStr, String endDateStr){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List result = new ArrayList();
        try {
            Date startDate = sdf.parse(startDateStr);
            Date endDate = sdf.parse(endDateStr);
            // 查询老师关联的课程表
            Long courseId = teacherService.selectById(teacherId).getCourseId();
            // 课程表所有时间段
            List<SpokenCourseTime> spokenCourseTimes = courseTimeService.selectByCourseId(courseId);
            // 查询当前教师关联的时间段
            List<SpokenTeacherCourseTime> spokenTeacherCourseTimes = teacherCourseTimeService.selectByTeacherId(teacherId);
            for (SpokenCourseTime spokenCourseTime : spokenCourseTimes) {
                Map rows = new HashMap();   // 每行数据
                Map time = new HashMap();   // 行头 时间
                List columns = new ArrayList(); // 星期一 ~ 星期日的集合

                time.put("startTime", spokenCourseTime.getStartTime());
                time.put("endTime", spokenCourseTime.getEndTime());
                rows.put("time", time);

                startDate = sdf.parse(startDateStr);
                // 星期一到星期日的遍历
                while(!startDate.after(endDate)){
                    Calendar c = Calendar.getInstance();
                    c.setTime(startDate);
                    String date = sdf.format(c.getTime());
                    // 日期对应的星期几
                    int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
                    if(dayOfWeek == 1){
                        dayOfWeek = 7;
                    }else{
                        dayOfWeek -= 1;
                    }

                    Map column = new HashMap(); // 星期 X的数据
                    column.put("chooseDate", date);
                    column.put("timeId", spokenCourseTime.getTimeId());
                    column.put("weekNum", dayOfWeek);
                    column.put("teacherId", teacherId);

                    // 查询当前时间段是否被教师关联
                    List<SpokenTeacherCourseTime> collect = spokenTeacherCourseTimes.stream().filter(item -> item.getCourseTime().getTimeId().equals(spokenCourseTime.getTimeId())).collect(Collectors.toList());
                    // 未被关联
                    if(collect.size() < 1){
                        column.put("columnColor", "gray");
                    } else{
                        SpokenTeacherCourseTime spokenTeacherCourseTime = collect.get(0);
                        // 获取当前时间段所关联的周几
                        List days = Arrays.stream(spokenTeacherCourseTime.getDays().split(",")).map(item -> Integer.valueOf(item)).collect(Collectors.toList());
                        // 当前时间段、当前星期几 已被教师选中
                        if(days.contains(dayOfWeek)){
                            column.put("columnColor", "white");
                        }
                        // 当前时间段、当前星期几 教师未选中
                        else{
                            column.put("columnColor", "gray");
                        }
                        // 查询教师ID、当前日期、当前时间段是否被用户选中
                        SpokenUserCourseTime userCourseTime = new SpokenUserCourseTime();
                        userCourseTime.setTeacherId(teacherId);
                        userCourseTime.setChooseDate(LocalDate.parse(date));
                        userCourseTime.setTimeId(spokenTeacherCourseTime.getCourseTimeId());
                        List<SpokenUserCourseTime> userCourseTimeList = select(userCourseTime);
                        // 是否有预约已消课的
                        List<SpokenUserCourseTime> cancelLesson = userCourseTimeList.stream().filter(item -> item.getStatus().equals(UserCourseTimeStatus.CANCEL_LESSON.getCode())).collect(Collectors.toList());
                        if(cancelLesson.size() > 0){
                            column.put("columnColor", "blue");
                            column.put("uctId", cancelLesson.get(0).getUctId());
                        }
                        // 是否有预约未消课的
                        List<SpokenUserCourseTime> noCancelLesson = userCourseTimeList.stream().filter(item -> item.getStatus().equals(UserCourseTimeStatus.NORMAL.getCode())).collect(Collectors.toList());
                        if(noCancelLesson.size() > 0){
                            column.put("columnColor", "green");
                            column.put("uctId", noCancelLesson.get(0).getUctId());
                        }
                    }

                    columns.add(column);

                    c.add(Calendar.DATE, 1);
                    startDate = c.getTime();
                }
                rows.put("columns", columns);
                result.add(rows);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public Map selectTipsInfoByUctId(Long uctId) {
        SpokenUserCourseTime userCourseTime = selectIdByPrimaryKey(uctId);
        Map<String, Object> stringObjectMap = orderService.selectById(userCourseTime.getOrderId());
        return stringObjectMap;
    }

    @Override
    public Integer selectTeacherCancelLessonCount(Long teacherId, String startDate, String endDate) {
        return userCourseTimeMapper.selectTeacherCancelLessonCount(teacherId, startDate, endDate);
    }

    /***
     * 查询距离上课时间两小时内的课程信息
     * @return
     */
    @Override
    public List<SpokenUserCourseTime> select2HoursFromClass(String date) {
        return userCourseTimeMapper.select2HoursFromClass(date);
    }
}
